package gogoqiu.java.base.http.utils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;

import okhttp3.MediaType;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.GzipSource;

/*
result
 */
public abstract class BaseResponseCheck <ResponseType> {

    private final static String TAG = BaseResponseCheck.class.getSimpleName();

    boolean io_error;

    ResponseType data;

    public BaseResponseCheck(){
        io_error = false;
    }

    public ResponseType getResult( final String url, final Response response ){
        ResponseBody responseBody = response.body();

        long contentLength = responseBody.contentLength();
        boolean successful = response.code()==200;
        boolean gzip = "gzip".equals(response.headers().get("Content-Encoding"));
        boolean gsonParsedResult = false;
        String content = "";

        if ( responseBody!=null ) {
            content = getContent( responseBody, gzip );
        }
        if( successful ){
            gsonParsedResult = preParse( content );
        }
        if( successful && gsonParsedResult ){
            //is_200 and !NullResponseBody and responseTypeCheck
            return data;
        }else {
            return getAlternativeContent( url, response.code(), 
                contentLength, content, gsonParsedResult );
        }
    }

    private String getContent(@NotNull ResponseBody responseBody, boolean gzip ){
        String body = null;
        try {
            BufferedSource source = responseBody.source();
            source.request(Long.MAX_VALUE);
            Buffer buffer = source.buffer();

            if ( gzip ) {
                GzipSource gzippedResponseBody = new GzipSource(buffer.clone());
                buffer = new Buffer();
                buffer.writeAll(gzippedResponseBody);
            }

            MediaType contentType = responseBody.contentType();
            Charset charset;
            if (contentType == null || contentType.charset(StandardCharsets.UTF_8) == null) {
                charset = StandardCharsets.UTF_8;
            } else {
                charset = contentType.charset(StandardCharsets.UTF_8);
            }
            assert charset != null;
            body = buffer.clone().readString ( charset );
        }catch (IOException e){
            io_error = true;
            body = "";
        }
        return body;
    }

    abstract protected ResponseType getAlternativeContent( String url, int code, long contentLength, 
        String content, boolean gsonParsedResult );

    /*
    return new TypeToken<ResponseType>() { }.getType();
    return new TypeToken<List<ResponseType>>() { }.getType();
     */
    //abstract public Type getType();
    abstract public Type getGsonParseType();

    boolean preParse( String body ){
        //Type type = new TypeToken<ResponseType>() { }.getType();
        Gson gson = new Gson();
        try{
            /*
            如果是List封装的数据，只能保证List的检测。无法投射到内部数据的转换
             */
            data = gson.fromJson( body, getGsonParseType() );
            return true;
        }catch ( Exception e ){
            return false;
        }
    }
}
